package com.soa.zuul.service;

import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.hibernate.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.soa.zuul.entity.GatewayHttpApi;
import com.soa.zuul.entity.GatewayLimit;
import com.soa.zuul.util.CodeMsg;
import com.soa.zuul.util.Constant;
import com.soa.zuul.util.Json;





@Service
@Transactional
public class AppLimitService {
	public final static Logger logger = LoggerFactory.getLogger(AppLimitService.class);
	@PersistenceContext
	private EntityManager entityManager;
	@Resource
	StringRedisTemplate stringRedisTemplate;
	private Session session;

	public EntityManager getEntityManager() {
		return entityManager;
	}

	public Session getSession() {
		return this.getEntityManager().unwrap(org.hibernate.Session.class);
	}

	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
	}
	
	
	/**
	 * 基于APP的限流
	 * @param id
	 * @return
	 */
	public CodeMsg getLimit(GatewayHttpApi gatewayHttpApi) {
		CodeMsg codeMsg = CodeMsg.SUCCESS;
		String key=GatewayHttpApi.class.getSimpleName()+":limit:"+gatewayHttpApi.getId();
		String gatewaylimitConfig = stringRedisTemplate.opsForValue().get(key);
		if(gatewaylimitConfig!=null){
			GatewayLimit gatewayLimit = Json.GSON.fromJson( gatewaylimitConfig,GatewayLimit.class);
			if(Constant.stateIsYes.equals(gatewayLimit.getState())){
				Integer limitNum=gatewayLimit.getLimitNum();
				String limitType = gatewayLimit.getLimitType();
				Integer limitTime = gatewayLimit.getLimitTime();
				TimeUnit timeUnit = TimeUnit.SECONDS;
				//分钟
				if(Constant.limitTypeMinus.equals(limitType)){
					timeUnit = TimeUnit.MINUTES;
				}
				//小时
				if(Constant.limitTypeHourse.equals(limitType)){
					timeUnit = TimeUnit.HOURS;
				}
				//天
				if(Constant.limitTypeDay.equals(limitType)){
					timeUnit = TimeUnit.DAYS;
				}
				String limitkey =GatewayLimit.class.getSimpleName()+":app-rate-limit:"+gatewayHttpApi.getId();
				if (!stringRedisTemplate.hasKey(limitkey)) {
					stringRedisTemplate.opsForValue().set(limitkey, "0", limitTime, timeUnit);
	            }
				// 当集群中当前秒的并发量达到了设定的值，不进行处理，注意集群中的网关所在服务器时间必须同步
	            if (stringRedisTemplate.opsForValue().increment(limitkey, 1) > limitNum) {
	            	codeMsg = CodeMsg.RATE_LIMIT_ERROR;
	    			return codeMsg;
	            }
			}
		}
		return codeMsg;
	}
}
